import { afterEach, beforeEach, vi } from 'vitest';
import { createPinia, setActivePinia } from 'pinia';
import { config } from '@vue/test-utils';

// Mock services
vi.mock('../../src/services/ImageUploadService', () => ({
  default: {
    uploadImages: vi.fn().mockImplementation(async (files, onProgress) => {
      const uploadedImages = files.map((file, index) => ({
        id: `test-${index}`,
        file,
        url: 'blob:test',
        name: file.name,
        width: 100,
        height: 100,
        fileSize: file.size,
        format: file.name.endsWith('.png') ? 'png' : 'jpg'
      }));
      
      if (onProgress) {
        onProgress(100);
      }
      
      return uploadedImages;
    }),
    removeImage: vi.fn(),
    validateImage: vi.fn().mockReturnValue(true)
  }
}));

vi.mock('../../src/services/ImageStitchingService', () => ({
  default: {
    stitchImages: vi.fn().mockImplementation(async (images, options, onProgress) => {
      const stitchedImage = {
        id: 'stitched-1',
        canvas: document.createElement('canvas'),
        width: 300,
        height: 150,
        url: 'blob:stitched'
      };
      
      if (onProgress) {
        onProgress(100);
      }
      
      return stitchedImage;
    }),
    generateMetadata: vi.fn().mockImplementation((images, stitchedImage, options) => ({
      version: '1.0',
      timestamp: Date.now(),
      stitchedImageSize: {
        width: stitchedImage.width,
        height: stitchedImage.height
      },
      backgroundColor: options?.backgroundColor || '#ffffff',
      images: images.map((img, index) => ({
        id: img.id,
        name: img.name,
        x: index * 100,
        y: 0,
        width: img.width,
        height: img.height,
        format: img.format
      }))
    })),
    downloadStitchedImage: vi.fn(),
    downloadMetadata: vi.fn(),
    embedMetadataInImage: vi.fn().mockResolvedValue('')
  }
}));

vi.mock('../../src/services/ImageRestorationService', () => ({
  default: {
    validateMetadata: vi.fn().mockResolvedValue({ valid: true }),
    restoreImages: vi.fn().mockImplementation(async (image, metadata, onProgress) => {
      const restoredImages = metadata.images.map(img => ({
        id: img.id,
        name: img.name,
        canvas: document.createElement('canvas'),
        width: img.width,
        height: img.height,
        url: `blob:restored-${img.id}`,
        format: img.format
      }));
      
      if (onProgress) {
        onProgress(100);
      }
      
      return restoredImages;
    }),
    downloadRestoredImage: vi.fn(),
    downloadAsZip: vi.fn()
  }
}));

// Setup global mocks
beforeEach(() => {
  // Create a fresh Pinia instance for each test
  setActivePinia(createPinia());
  
  // Mock canvas and related APIs
  global.HTMLCanvasElement.prototype.getContext = vi.fn().mockReturnValue({
    drawImage: vi.fn(),
    fillRect: vi.fn(),
    fillStyle: '',
    getImageData: vi.fn().mockReturnValue({
      data: new Uint8ClampedArray(4),
      width: 1,
      height: 1
    }),
    putImageData: vi.fn()
  });
  
  // Mock canvas toBlob and toDataURL
  global.HTMLCanvasElement.prototype.toBlob = vi.fn().mockImplementation(callback => {
    callback(new Blob(['test']));
  });
  
  global.HTMLCanvasElement.prototype.toDataURL = vi.fn().mockReturnValue('');
  
  // Mock URL methods
  global.URL.createObjectURL = vi.fn().mockReturnValue('blob:test');
  global.URL.revokeObjectURL = vi.fn();
  
  // Mock Image
  global.Image = vi.fn().mockImplementation(() => ({
    onload: null,
    onerror: null,
    src: '',
    width: 100,
    height: 100
  }));
  
  // Mock Worker
  global.Worker = vi.fn().mockImplementation(() => ({
    postMessage: vi.fn(),
    onmessage: null,
    onerror: null,
    terminate: vi.fn()
  }));
  
  // Mock FileReader
  global.FileReader = vi.fn().mockImplementation(() => ({
    readAsDataURL: vi.fn(),
    onload: null,
    onerror: null,
    result: ''
  }));
  
  // Mock document methods
  const originalCreateElement = document.createElement;
  document.createElement = vi.fn().mockImplementation((tag) => {
    if (tag === 'canvas') {
      return {
        width: 0,
        height: 0,
        getContext: vi.fn().mockReturnValue({
          drawImage: vi.fn(),
          fillRect: vi.fn(),
          fillStyle: '',
          getImageData: vi.fn().mockReturnValue({
            data: new Uint8ClampedArray(4),
            width: 1,
            height: 1
          }),
          putImageData: vi.fn()
        }),
        toBlob: vi.fn().mockImplementation(callback => {
          callback(new Blob(['test']));
        }),
        toDataURL: vi.fn().mockReturnValue('')
      };
    }
    if (tag === 'a') {
      return {
        href: '',
        download: '',
        click: vi.fn(),
        style: {}
      };
    }
    return originalCreateElement.call(document, tag);
  });
});

// Clean up after each test
afterEach(() => {
  vi.clearAllMocks();
});

// Configure Vue Test Utils
config.global.stubs = {
  transition: false,
  'router-link': true,
  'router-view': true
};